<?php
namespace api\modules\v1\models;

use api\components\ApiModel;
use common\models\ARBrokerAmount;
use common\models\ARNeed;
use common\models\AROrder;
use common\models\AROrderEvaluate;
use common\models\AROrderTime;
use common\models\ARServiceCharge;
use common\models\ARUser;
use Yii;
use yii\helpers\ArrayHelper;

/**
 * 交易流程模型
 * @author WJ
 */
class Order extends ApiModel
{
    const SCENARIO_ACCEPT_BUY = 'accept_buy';
    const SCENARIO_LIST = 'list';
    const SCENARIO_ACCEPT_SELL = 'accept_sell';
    const SCENARIO_SELECT_BROKER = 'select_broker';
    const SCENARIO_CONFIRM = 'confirm';
    const SCENARIO_REFUSE = 'refuse';
    const SCENARIO_INFO = 'info';
    const SCENARIO_BUYER_TRANSFER = 'buyer_transfer';
    const SCENARIO_RECEIVE_MONEY = 'receive_money';
    const SCENARIO_RECENT_LIST = 'recent_list';

    public $need_id;
    public $amount;
    public $memo;
    public $order_id;
    public $broker_id;
    public $actiontype;
    public $size;
    public $page;

    protected $_need;

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'need_id'    => '需求编号',
            'amount'     => '交易数量',
            'memo'       => '留言',
            'order_id'   => '订单编号',
            'broker_id'  => '经纪人编号',
            'actiontype' => '交易中动作类型',
            'size'       => '分页大小',
            'page'       => '当前页',
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        return [
            self::SCENARIO_ACCEPT_BUY     => ['need_id', 'amount', 'memo'],
            self::SCENARIO_ACCEPT_SELL    => ['need_id', 'amount', 'memo'],
            self::SCENARIO_LIST           => ['page', 'size', 'actiontype'],
            self::SCENARIO_SELECT_BROKER  => ['order_id', 'broker_id'],
            self::SCENARIO_CONFIRM        => ['order_id'],
            self::SCENARIO_REFUSE         => ['order_id'],
            self::SCENARIO_INFO           => ['order_id'],
            self::SCENARIO_BUYER_TRANSFER => ['order_id'],
            self::SCENARIO_RECEIVE_MONEY  => ['order_id'],
            self::SCENARIO_RECENT_LIST    => ['size'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['need_id', 'order_id', 'broker_id', 'amount', 'memo'], 'trim'],
            [['need_id', 'order_id', 'broker_id', 'amount', 'actiontype'], 'required'],
            ['amount', 'double'],
            ['need_id', 'needCheck'],
            ['amount', 'amountCheck'],
            [['order_id'], 'required', 'on' => [self::SCENARIO_CONFIRM]],
            ['actiontype', 'in', 'range' => [AROrder::ACTION_TYPE_LAUNCH, AROrder::ACTION_TYPE_ACCEPT, AROrder::ACTION_TYPE_BROKE]],
            ['memo', 'string', 'max' => 255],
            ['size', 'default', 'value' => 10],
            ['page', 'default', 'value' => 1],
        ];
    }

    /**
     * 需求校验
     */
    public function needCheck($attribute, $params)
    {
        $scenario = $this->getScenario();
        if ($scenario == self::SCENARIO_ACCEPT_BUY) {
            //接下挂买需求
            $need = ARNeed::findOne(['id' => $this->need_id, 'type' => ARNeed::TYPE_IN]);
        } elseif ($scenario == self::SCENARIO_ACCEPT_SELL) {
            //接下挂卖需求
            $need = ARNeed::findOne(['id' => $this->need_id, 'type' => ARNeed::TYPE_OUT]);
        }
        if (!$need) {
            $this->throwError('500011');
        } elseif (Yii::$app->user->id == $need->uid) {
            $this->throwError('400051');
        } elseif ($need->expired_at != -1 && $need->expired_at > Yii::$app->formatter->asTimestamp('now')) {
            $this->throwError('500016');
        }
        $this->_need = $need;
    }

    /**
     * 购买数量校验
     */
    public function amountCheck($attribute, $params)
    {
        $need = $this->_need;
        $scale = Yii::$app->params['scale'];
        $amount = sprintf("%.{$scale}f", $this->amount);
        if (bccomp($amount, sprintf("%.{$scale}f", $need->amount_max), $scale) == 1) {
            //大于最大限额
            $this->throwError('500013');
        } elseif (bccomp($amount, sprintf("%.{$scale}f", $need->amount_min), $scale) == -1) {
            //小于最小额度
            $this->throwError('500014');
        } elseif (bccomp($amount, sprintf("%.{$scale}f", $need->amount_remain), $scale) == 1) {
            //大于剩下数量
            $this->throwError('500015');
        }
    }

    /**
     * 获取订单安全码
     * @param Object $row 数据记录
     */
    public static function getOrderSecufity($row)
    {
        $salt = Yii::$app->params['salt']['order'];
        $param = [
            'need_id'         => $row->need_id,
            'uid'             => $row->uid,
            'trans_mode'      => $row->trans_mode,
            'type'            => $row->type,
            'currency'        => $row->currency,
            'coin'            => $row->coin,
            'opp_uid'         => $row->opp_uid,
            'broker'          => $row->broker,
            'total_price'     => floatval($row->total_price),
            'broker_charge'   => floatval($row->broker_charge),
            'platform_charge' => floatval($row->platform_charge),
            'amount'          => floatval($row->amount),
            'status'          => $row->status,
        ];
        $addtime = $row->security_at;
        $code = self::getSecurity($param, $addtime, $salt);
        return $code;
    }

    /**
     * 校验订单安全码
     * @param Object $row 数据记录
     */
    public static function verifyOrderSecufity($row)
    {
        $code = self::getOrderSecufity($row);
        if ($code === $row->security_code) {
            return true;
        } else {
            return false;
        }
    }

    public function getIdentity($type, $uid, $opp_uid, $broker)
    {
        $indentityUid = Yii::$app->user->id;
        if ($indentityUid == $broker) {
            return AROrder::IDENTITY_BROKER;
        }
        if ($type == AROrder::TYPE_IN) {
            //挂买
            if ($indentityUid == $uid) {
                return AROrder::IDENTITY_BUY;
            } elseif ($indentityUid == $opp_uid) {
                return AROrder::IDENTITY_SELL;
            }
        }
        if ($type == AROrder::TYPE_OUT) {
            //挂卖
            if ($indentityUid == $uid) {
                return AROrder::IDENTITY_SELL;
            } elseif ($indentityUid == $opp_uid) {
                return AROrder::IDENTITY_BUY;
            }
        }
        return null;
    }

    /**
     * 获取用户指定币种的成交量(买家、卖家)
     */
    public function getTransAmount($uid, $coin)
    {
        $transcount = AROrder::find()->where(['and', ['status' => AROrder::STATUS_SUCCESS], ['or', ['uid' => $uid], ['opp_uid' => $uid]]])->sum('amount');
        return $transcount;
    }

    /**
     * 获取用户指定币种的成交量(经纪人)
     */
    public function getBrokerTransAmount($uid, $coin)
    {
        $transcount = AROrder::find()->where(['and', ['status' => AROrder::STATUS_SUCCESS], ['broker' => $uid]])->sum('amount');
        return $transcount;
    }

    /**
     * 接下挂买需求
     */
    public function acceptBuy()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $need = $this->_need;
        $scale = Yii::$app->params['scale'];
        $amount = sprintf("%.{$scale}f", $this->amount);
        $tran = Yii::$app->db->beginTransaction();
        try {
            //更新需求
            $need->setScenario(ARNeed::SCENARIO_BUY);
            $need->amount_trading = bcadd(sprintf("%.{$scale}f", $need->amount_trading), $amount, $scale);
            $need->amount_remain = bcsub(sprintf("%.{$scale}f", $need->amount_remain), $amount, $scale);
            $need->update();

            //产生订单记录
            $order = new AROrder();
            $order->need_id = $need->id;
            $order->uid = $need->uid;
            $order->trans_mode = $need->trans_mode;
            $order->type = AROrder::TYPE_IN;
            $order->currency = $need->currency;
            $order->coin = $need->coin;
            $order->opp_uid = Yii::$app->user->id;
            $order->amount = $amount;
            $order->broker_charge = bcmul(sprintf("%.{$scale}f", Yii::$app->params['server_charge']['broker']), $amount, $scale);
            $order->platform_charge = bcmul(sprintf("%.{$scale}f", Yii::$app->params['server_charge']['platform']), $amount, $scale);
            $order->total_price = bcmul(sprintf("%.{$scale}f", $need->price), $amount, $scale);
            $order->status = AROrder::STATUS_COMMUNICATION;
            $order->security_at = Yii::$app->formatter->asTimeStamp('now');
            $security_code = self::getOrderSecufity($order);
            $order->security_code = $security_code;
            $order->save();

            //冻币
            Assets::beSelling($order->id, Yii::$app->user->id, $need->coin, $order->amount);

            //产生订单时间记录
            $order_time = new AROrderTime();
            $order_time->order_id = $order->id;
            $order_time->save();

            //生成提示信息
            $user = self::getUser();
            MessagePrompt::addPrompt('join-need', $user, $order->uid, $order->id);

            // 生成聊天信息
            Chat::addSystemMessage($user, $order->id, 'accept_need');
            if ($this->memo) {
                Chat::addUserMessage($user, $order->id, $this->memo);
            }

            $tran->commit();
        } catch (\Exception $e) {
            $tran->rollBack();
            throw $e;
        }
        return ['order_id' => $order->id];
    }

    /**
     * add by zcy
     * 订单列表
     */
    public function orderlist()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $uid = Yii::$app->user->id;
        $model = AROrder::find();
        if ($this->actiontype == AROrder::ACTION_TYPE_LAUNCH) {
            $model->andWhere([AROrder::tableName() . '.uid' => $uid]);
        } elseif ($this->actiontype == AROrder::ACTION_TYPE_ACCEPT) {
            $model->andWhere([AROrder::tableName() . '.opp_uid' => $uid]);
        } else {
            $model->andWhere([AROrder::tableName() . '.broker' => $uid]);
        }

        $model->with(['user', 'oppUser', 'coinType', 'currencyType', 'serviceCharge']);
        $count = $model->count();
        $data = $model->limit($this->size)->offset($this->size * ($this->page - 1))->all();
        $rows = ArrayHelper::toArray($data, [
            AROrder::className() => [
                'id',
                'type',
                'launcher'             => function ($row) {
                    return $row->user->nickname;
                },
                'accepter'             => function ($row) {
                    return $row->oppUser->nickname;
                },
                'coin'                 => function ($row) {
                    return $row->coinType->name;
                },
                'currency'             => function ($row) {
                    return $row->currencyType->name;
                },
                'amount',
                'total_price',
                'broker_charge',
                'servicecharge_status' => function ($row) {
                    return $row->serviceCharge ? $row->serviceCharge->status : ARServiceCharge::STATUSTRANSFER;
                },
                'status',
                'createtime'           => function ($row) {
                    return Yii::$app->formatter->asDatetime($row->created_at);
                },
                'security'             => function ($row) {
                    $flag = self::verifyOrderSecufity($row);
                    return ($flag) ? AROrder::SECURITY_SAFE : AROrder::SECURITY_UNSAFE;
                },
            ],
        ]);
        return ['count' => $count, 'rows' => $rows];
    }

    /**
     * 接下挂卖需求
     */
    public function acceptSell()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $need = $this->_need;
        $scale = Yii::$app->params['scale'];
        $amount = sprintf("%.{$scale}f", $this->amount);
        $tran = Yii::$app->db->beginTransaction();
        try {
            //更新需求
            $need->setScenario(ARNeed::SCENARIO_SELL);
            $need->amount_trading = bcadd(sprintf("%.{$scale}f", $need->amount_trading), $amount, $scale);
            $need->amount_remain = bcsub(sprintf("%.{$scale}f", $need->amount_remain), $amount, $scale);
            $need->update();

            //产生订单记录
            $order = new AROrder();
            $order->need_id = $need->id;
            $order->uid = $need->uid;
            $order->trans_mode = $need->trans_mode;
            $order->type = AROrder::TYPE_OUT;
            $order->currency = $need->currency;
            $order->coin = $need->coin;
            $order->opp_uid = Yii::$app->user->id;
            $order->amount = $amount;
            $order->broker_charge = bcmul(sprintf("%.{$scale}f", Yii::$app->params['server_charge']['broker']), $amount, $scale);
            $order->platform_charge = bcmul(sprintf("%.{$scale}f", Yii::$app->params['server_charge']['platform']), $amount, $scale);
            $order->total_price = bcmul(sprintf("%.{$scale}f", $need->price), $amount, $scale);
            $order->status = AROrder::STATUS_COMMUNICATION;
            $order->security_at = Yii::$app->formatter->asTimeStamp('now');
            $security_code = self::getOrderSecufity($order);
            $order->security_code = $security_code;
            $order->save();

            //产生订单时间记录
            $order_time = new AROrderTime();
            $order_time->order_id = $order->id;
            $order_time->save();

            //生成提示信息
            $user = self::getUser();
            MessagePrompt::addPrompt('join-need', $user, $order->uid, $order->id);

            // 生成聊天信息
            Chat::addSystemMessage($user, $order->id, 'accept_need');
            if ($this->memo) {
                Chat::addUserMessage($user, $order->id, $this->memo);
            }

            $tran->commit();
        } catch (\Exception $e) {
            $tran->rollBack();
            throw $e;
        }
        return ['order_id' => $order->id];
    }

    /**
     * 确认交易
     * @author CGA
     */
    public function confirm()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $uid = Yii::$app->user->id;
        $user = self::getUser();
        $scale = Yii::$app->params['scale'];
        $order = AROrder::find()->where(['id' => $this->order_id])->one();
        if (!$order) {
            self::throwError('500004');
        }
        $orderFlag = self::verifyOrderSecufity($order);
        if (!$orderFlag) {
            self::throwError('500017');
        }
        if (($order->type == AROrder::TYPE_OUT && $order->uid == $uid) || ($order->type == AROrder::TYPE_IN && $order->opp_uid == $uid)) {
            //卖方确认
            if ($order->type == AROrder::TYPE_OUT && $order->u_status != AROrder::USER_STATUS_UNCOMFIRM || ($order->type == AROrder::TYPE_IN && $order->opp_status != AROrder::USER_STATUS_UNCOMFIRM)) {
                self::throwError('500008');
            }
            $transaction = Yii::$app->db->beginTransaction();
            try {
                if ($order->type == AROrder::TYPE_OUT) {
                    $timeFlag = ReplyTime::updateOrderDemanderTime($this->order_id);
                    $order->u_status = AROrder::USER_STATUS_CONFIRM;
                    if ($order->opp_status == AROrder::USER_STATUS_CONFIRM && $order->broker_status == AROrder::USER_STATUS_CONFIRM) {
                        $order->status = AROrder::STATUS_START;
                        $total = bcadd(bcadd(sprintf("%.{$scale}f", $order->amount), sprintf("%.{$scale}f", $order->broker_charge), $scale), sprintf("%.{$scale}f", $order->platform_charge), $scale);
                        $flag = Assets::trade($order->id, $order->uid, $order->coin, $total);
                    }
                } else {
                    $timeFlag = ReplyTime::updateOrderSupplierTime($this->order_id);
                    $order->opp_status = AROrder::USER_STATUS_CONFIRM;
                    if ($order->u_status == AROrder::USER_STATUS_CONFIRM && $order->broker_status == AROrder::USER_STATUS_CONFIRM) {
                        $order->status = AROrder::STATUS_START;
                        $flag = Assets::trade($order->id, $order->opp_uid, $order->coin, $order->amount);
                    }
                }
                if (!$timeFlag) {
                    self::throwError('500005');
                }
                $order->security_at = Yii::$app->formatter->asTimestamp('now');
                $order->security_code = self::getOrderSecufity($order);
                if (!$order->update()) {
                    self::throwError('500006');
                }
                Chat::addSystemMessage($user, $order->id, 'confirm-order');
                $transaction->commit();
                return true;
            } catch (\Exception $e) {
                $transaction->rollBack();
                throw $e;
            }
        } elseif (($order->type == AROrder::TYPE_IN && $order->uid == $uid) || ($order->type == AROrder::TYPE_OUT && $order->opp_uid == $uid)) {
            //买方确认
            if ($order->type == AROrder::TYPE_IN && $order->u_status != AROrder::USER_STATUS_UNCOMFIRM || ($order->type == AROrder::TYPE_OUT && $order->opp_status != AROrder::USER_STATUS_UNCOMFIRM)) {
                self::throwError('500008');
            }
            $transaction = Yii::$app->db->beginTransaction();
            try {
                if ($order->type == AROrder::TYPE_OUT) {
                    $timeFlag = ReplyTime::updateOrderSupplierTime($this->order_id);
                    $order->opp_status = AROrder::USER_STATUS_CONFIRM;
                    if ($order->u_status == AROrder::USER_STATUS_CONFIRM && $order->broker_status == AROrder::USER_STATUS_CONFIRM) {
                        $order->status = AROrder::STATUS_START;
                        $total = bcadd(bcadd(sprintf("%.{$scale}f", $order->amount), sprintf("%.{$scale}f", $order->broker_charge), $scale), sprintf("%.{$scale}f", $order->platform_charge), $scale);
                        $flag = Assets::trade($order->id, $order->uid, $order->coin, $total);
                    }
                } else {
                    $timeFlag = ReplyTime::updateOrderDemanderTime($this->order_id);
                    $order->u_status = AROrder::USER_STATUS_CONFIRM;
                    if ($order->opp_status == AROrder::USER_STATUS_CONFIRM && $order->broker_status == AROrder::USER_STATUS_CONFIRM) {
                        $order->status = AROrder::STATUS_START;
                        $flag = Assets::trade($order->id, $order->opp_uid, $order->coin, $order->amount);
                    }
                }
                if (!$timeFlag) {
                    self::throwError('500005');
                }
                $order->security_at = Yii::$app->formatter->asTimestamp('now');
                $order->security_code = self::getOrderSecufity($order);
                if (!$order->update()) {
                    self::throwError('500006');
                }
                Chat::addSystemMessage($user, $order->id, 'confirm-order');
                $transaction->commit();
                return true;

            } catch (\Exception $e) {
                $transaction->rollBack();
                throw $e;
            }
        } elseif ($order->broker == $uid) {
            //经纪人确认
            if ($order->broker_status != AROrder::USER_STATUS_UNCOMFIRM) {
                self::throwError('500008');
            }
            $transaction = Yii::$app->db->beginTransaction();
            try {
                $flag = Assets::vouch($this->order_id, $uid, $order->coin, $order->amount);
                if ($flag) {
                    $timeFlag = ReplyTime::updateOrderBrokerTime($this->order_id);
                    if (!$timeFlag) {
                        self::throwError('500005');
                    }
                    $order->broker_status = AROrder::USER_STATUS_CONFIRM;
                    if ($order->type == AROrder::TYPE_OUT) {
                        if ($order->u_status == AROrder::USER_STATUS_CONFIRM && $order->opp_status == AROrder::USER_STATUS_CONFIRM) {
                            $total = bcadd(bcadd(sprintf("%.{$scale}f", $order->amount), sprintf("%.{$scale}f", $order->broker_charge), $scale), sprintf("%.{$scale}f", $order->platform_charge), $scale);
                            $flag = Assets::trade($order->id, $order->uid, $order->coin, $total);
                            $order->status = AROrder::STATUS_START;
                        }
                    } else {
                        if ($order->u_status == AROrder::USER_STATUS_CONFIRM && $order->opp_status == AROrder::USER_STATUS_CONFIRM) {
                            $order->status = AROrder::STATUS_START;
                            $flag = Assets::trade($order->id, $order->opp_uid, $order->coin, $order->amount);
                        }
                    }
                    $order->security_at = Yii::$app->formatter->asTimestamp('now');
                    $order->security_code = self::getOrderSecufity($order);
                    if (!$order->update()) {
                        self::throwError('500006');
                    }
                    Chat::addSystemMessage($user, $order->id, 'confirm-order');
                    $transaction->commit();
                    return true;
                }
            } catch (\Exception $e) {
                $transaction->rollBack();
                throw $e;
            }
        } else {
            self::throwError('500007');
        }
    }

    /**
     * 拒绝交易
     * @author WJ
     */
    public function refuse()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $uid = Yii::$app->user->id;
        $order = AROrder::find()->where(['and', ['id' => $this->order_id], ['or', ['uid' => $uid], ['opp_uid' => $uid], ['broker' => $uid]]])->one();
        if (!$order) {
            //订单不存在
            $this->throwError('500004');
        } elseif (!self::verifyOrderSecufity($order)) {
            //订单信息异常
            $this->throwError('500017');
        } elseif ($order->status != AROrder::STATUS_COMMUNICATION && $order->status != AROrder::STATUS_START) {
            //订单不可操作
            $this->throwError('500102');
        } elseif( 
            ($order->status == AROrder::STATUS_COMMUNICATION && (($order->uid == $uid && $order->u_status == AROrder::USER_STATUS_CONFIRM) ||($order->opp_uid == $uid && $order->opp_status == AROrder::USER_STATUS_CONFIRM) ||($order->broker == $uid && $order->broker_status == AROrder::USER_STATUS_CONFIRM))) //状态=交易中，若已拒绝则不能再操作
            || ($order->status == AROrder::STATUS_START && (($order->uid == $uid && $order->u_status == AROrder::USER_STATUS_REFUSE) || ($order->opp_uid == $uid && $order->opp_status == AROrder::USER_STATUS_REFUSE) || ($order->broker == $uid) )  ) //状态=开始交易，若已拒绝不能再拒绝
        ){
            $this->throwError('500102');
        }
        $tran = Yii::$app->db->beginTransaction();
        try {
            $isSell = ($order->type == AROrder::TYPE_IN) ? false : true;
            $seller_id = ($order->type == AROrder::TYPE_IN)?$order->opp_uid:$order->uid;
            $status = $order->status;
            $broker_status = $order->broker_status;

            //更新订单
            if ($order->uid == $uid) {
                $order->u_status = AROrder::USER_STATUS_REFUSE;
            } elseif ($order->opp_uid == $uid) {
                $order->opp_status = AROrder::USER_STATUS_REFUSE;
            } elseif ($order->broker == $uid) {
                $order->broker_status = AROrder::USER_STATUS_REFUSE;
            }

            if($status == AROrder::STATUS_COMMUNICATION){   //交流中拒绝
                if($order->type == AROrder::TYPE_IN){
                    Assets::unfreeze($order->id, $seller_id, $order->coin, $order->amount);
                }
                if($order->broker && $broker_status == AROrder::USER_STATUS_CONFIRM){
                    Assets::assureReturn($order->id, $order->broker, $order->coin, $order->amount, 0);
                    //更改经纪人交易笔数
                    Broker::changeNum($order->broker, 2);
                }
                //更改订单
                Need::returnNeed($order->need_id, $order->amount);
                $status = AROrder::STATUS_CANCEL;
            } else {    //交易中拒绝
                if($order->u_status == AROrder::USER_STATUS_REFUSE && $order->opp_status == AROrder::USER_STATUS_REFUSE){
                    Assets::returnBack($order->id, $seller_id, $order->coin, $order->amount, $isSell, bcadd($order->platform_charge, $order->broker_charge));
                    Assets::assureReturn($order->id, $order->broker, $order->coin, $order->amount, 0);
                    $status = AROrder::STATUS_CANCEL;
                    //更改经纪人交易笔数
                    Broker::changeNum($order->broker, 2);
                    //更改订单
                    Need::returnNeed($order->need_id, $order->amount);
                }
            }
            $order->status = $status;
            $order->security_at = Yii::$app->formatter->asTimeStamp('now');
            $security_code = self::getOrderSecufity($order);
            $order->security_code = $security_code;
            $order->update();

            $tran->commit();
        } catch (\Exception $e) {
            $tran->rollBack();
            throw $e;
        }
        return ['order_id' => $order->id];
    }

    /**
     * 选择经纪人
     * @author WJ
     */
    public function selectBroker()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $order = AROrder::findOne($this->order_id);
        if (!$order) {
            //订单不存在
            $this->throwError('500004');
        } elseif (!self::verifyOrderSecufity($order)) {
            //订单信息异常
            $this->throwError('500017');
        } elseif ($order->status == AROrder::STATUS_CANCEL) {
            //订单已被取消
            $this->throwError('500009');
        } elseif ($order->status != AROrder::STATUS_COMMUNICATION) {
            //订单已开始，无法更换
            $this->throwError('500010');
        } elseif (($order->type == AROrder::TYPE_IN && $order->uid != Yii::$app->user->id) || ($order->type == AROrder::TYPE_OUT && $order->opp_uid != Yii::$app->user->id)) {
            //无权指定经纪人
            $this->throwError('300002');
        }
        $broker = ARUser::findOne(['id' => $this->broker_id, 'role' => ARUser::ROLE_AGENT]);
        if (!$broker) {
            //经纪人不存在
            $this->throwError('300003');
        } elseif (($broker->id == $order->uid) || ($broker->id == $order->opp_uid)) {
            //不能指定交易双方作为经纪人
            $this->throwError('300006');
        }
        $broker_amount = ARBrokerAmount::findOne(['uid' => $broker->id, 'coin' => $order->coin]);
        if (!$broker_amount) {
            //经纪人不担保该币种
            $this->throwError('300004');
        } elseif ($broker_amount->amount_remain < $order->amount) {
            //经纪人担保额不足
            $this->throwError('300005');
        }
        if ($order->broker != $broker->id) {
            $tran = Yii::$app->db->beginTransaction();
            try {
                $user = self::getUser();
                if ($order->broker == null) {
                    Chat::addSystemMessage($user, $order->id, 'select-broker', $broker);
                } else {
                    Chat::addSystemMessage($user, $order->id, 'change-broker', $broker);
                }
                $order->broker = $broker->id;
                $order->security_at = Yii::$app->formatter->asTimeStamp('now');

                $security_code = self::getOrderSecufity($order);
                $order->security_code = $security_code;
                if (!$order->update()) {
                    self::getErrorMessge($order);
                }

                $user = self::getUser();
                MessagePrompt::addPrompt('select-broker', $user, $broker->id, $order->id);

                $tran->commit();
            } catch (\Exception $e) {
                $tran->rollBack();
                throw $e;
            }

        }

        return ['broker_id' => $broker->id];
    }

    /**
     * add by zcy
     * 订单详情
     */
    public function orderinfo()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }

        $model = AROrder::find()->where([AROrder::tableName() . '.id' => $this->order_id]);
        $model->joinWith(['user', 'oppUser as tbl_oppUser', 'coinType', 'currencyType']);
        $order = $model->one();
        if (!$order) {
            //订单不存在
            $this->throwError('500004');
        }
        $uid = Yii::$app->user->id;
        if ($order->uid != $uid && $order->opp_uid != $uid && $order->broker != $uid) {
            $this->throwError('500007');
        }
        if (!self::verifyOrderSecufity($order)) {
            //订单信息异常
            $this->throwError('500017');
        }

        $orderinfo = ArrayHelper::toArray($order, [
            AROrder::className() => [
                'id',
                'status',
                'type',
                'need_id',
                'buy_id' => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->user->id;
                    } else {
                        return $row->oppUser->id;
                    }

                },
                'buy' => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->user->nickname;
                    } else {
                        return $row->oppUser->nickname;
                    }

                },
                'sell_id' => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->oppUser->id;
                    } else {
                        return $row->user->id;
                    }

                },
                'sell' => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->oppUser->nickname;
                    } else {
                        return $row->user->nickname;
                    }

                },
                'broker_id'   => 'broker',
                'amount',
                'coin'        => function ($row) {
                    return $row->coinType->name;
                },
                'total_price',
                'currency'    => function ($row) {
                    return $row->currencyType->name;
                },
                'charge'      => function ($row) {
                    return $row->broker_charge + $row->platform_charge;
                },
                'buy_status'  => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->u_status;
                    } else {
                        return $row->opp_status;
                    }
                },
                'sell_status' => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->opp_status;
                    } else {
                        return $row->u_status;
                    }
                },
                'broker_status',
                'identity'    => function ($row) {
                    return $this->getIdentity($row->type, $row->uid, $row->opp_uid, $row->broker);
                },
                'create_time' => function ($row) {
                    return Yii::$app->formatter->asDateTime($row->created_at);
                },

            ],
        ]);

        $buy = ARUser::find()->where(['id' => $orderinfo['buy_id']])->one();
        $buyinfo = ArrayHelper::toArray($buy, [
            ARUser::className() => [
                'id',
                'nickname',
                'transaction_num' => function ($row) {
                    return $row->scoring ? $row->scoring->transaction_num : 0;
                },
                'rating'          => function ($row) {
                    return $row->scoring ? $row->scoring->rating : 0;
                },
            ],
        ]);

        $buyinfo['transaction_amount'] = $this->getTransAmount($orderinfo['buy_id'], $orderinfo['coin']);

        $sell = ARUser::find()->where(['id' => $orderinfo['sell_id']])->one();
        $sellinfo = ArrayHelper::toArray($sell, [
            ARUser::className() => [
                'id',
                'nickname',
                'transaction_num' => function ($row) {
                    return $row->scoring ? $row->scoring->transaction_num : 0;
                },
                'rating'          => function ($row) {
                    return $row->scoring ? $row->scoring->rating : 0;
                },
            ],
        ]);

        $sellinfo['transaction_amount'] = $this->getTransAmount($orderinfo['sell_id'], $orderinfo['coin']);

        $broker = ARUser::find()->where(['id' => $orderinfo['broker_id']])->one();
        $brokerinfo = '';
        if ($broker) {
            $brokerinfo = ArrayHelper::toArray($broker, [
                ARUser::className() => [
                    'id',
                    'nickname',
                    'transaction_num' => function ($row) {
                        return $row->brokerScoring ? $row->brokerScoring->transaction_num : 0;
                    },
                    'rating'          => function ($row) {
                        return $row->brokerScoring ? $row->brokerScoring->rating : 0;
                    },
                ],
            ]);

            $brokerinfo['transaction_amount'] = $this->getBrokerTransAmount($orderinfo['broker_id'], $orderinfo['coin']);
        }

        if ($orderinfo['type'] == AROrder::TYPE_IN) {
            //买入
            $buyinfo['amount_remain'] = ARNeed::find()->where(['id' => $orderinfo['need_id']])->one()->amount_remain;
            $buyinfo['amount'] = $orderinfo['amount'];
        } else {
            $sellinfo['amount_remain'] = ARNeed::find()->where(['id' => $orderinfo['need_id']])->one()->amount_remain;
            $sellinfo['amount'] = $orderinfo['amount'];
        }

        $evalutateItems = [];
        if ($orderinfo['status'] == AROrder::STATUS_SUCCESS) {
            $evaluatemodel = AROrderEvaluate::find()->where(['uid' => Yii::$app->user->id, 'order_id' => $order->id]);
            $evaluat = $evaluatemodel->with('oppUser')->all();
            $evalutateItems = ArrayHelper::toArray($evaluat, [
                AROrderEvaluate::className() => [
                    'order_id',
                    'identity',
                    'opp_uid',
                    'nickname' => function ($row) {
                        return $row->oppUser->nickname;
                    },
                    'opp_rating',
                    'opp_appraise',
                ],
            ]);
        }

        $data = [
            'orderinfo'     => $orderinfo,
            'buyinfo'       => $buyinfo,
            'sellinfo'      => $sellinfo,
            'brokerinfo'    => $brokerinfo,
            'evaluateItems' => $evalutateItems,

        ];

        return $data;
    }

    /**
     * 买方确认转款
     * @author WJ
     */
    public function buyerTransfer()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $order = AROrder::find()->where(['and', ['id' => $this->order_id], ['or', ['uid' => Yii::$app->user->id], ['opp_uid' => Yii::$app->user->id]]])->one();
        if (!$order) {
            //订单不存在
            $this->throwError('500004');
        } elseif (!self::verifyOrderSecufity($order)) {
            //订单信息异常
            $this->throwError('500017');
        } elseif (($order->type == AROrder::TYPE_IN && $order->uid != Yii::$app->user->id) || ($order->type == AROrder::TYPE_OUT && $order->opp_uid != Yii::$app->user->id)) {
            //无权确认买家已转款
            $this->throwError('500018');
        } elseif ($order->status != AROrder::STATUS_START) {
            //订单状态更新失败
            $this->throwError('500102');
        }
        $tran = Yii::$app->db->beginTransaction();
        try {
            $order->status = AROrder::STATUS_BUYER_TRANSFER;
            $order->security_at = Yii::$app->formatter->asTimeStamp('now');
            $security_code = self::getOrderSecufity($order);
            $order->security_code = $security_code;
            if (!$order->update()) {
                self::getErrorMessge($order);
            }
            $timeFlag = ReplyTime::updateOrderBuyerTransfer($order->id); //更新买家转账时间
            if (!$timeFlag) {
                self::throwError('500005');
            }
            $user = self::getUser();
            Chat::addSystemMessage($user, $order->id, 'confirm-payment');
            $tran->commit();
        } catch (\Exception $e) {
            $tran->rollBack();
            throw $e;
        }

        return ['order_id' => $order->id];
    }

    /**
     * 卖方确认收款
     * @author CGA
     */
    public function sellerrRceiveMoney()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $uid = Yii::$app->user->id;
        $order = AROrder::find()->where(['id' => $this->order_id])->one();
        if (!$order) {
            self::throwError('500004');
        }
        $orderFlag = self::verifyOrderSecufity($order);
        if (!$orderFlag) {
            self::throwError('500017');
        }
        if ($order->status != AROrder::STATUS_BROKER_TRANSFER) {
            self::throwError('500102');
        }
        if (($order->type == AROrder::TYPE_OUT && $order->uid == $uid) || ($order->type == AROrder::TYPE_IN && $order->opp_uid == $uid)) {
            $transaction = Yii::$app->db->beginTransaction();
            try {
                $flag = Assets::assureReturn($order->id, $order->broker, $order->coin, $order->amount);
                if ($flag) {
                    $timeFlag = ReplyTime::updateOrderSellerReceipt($this->order_id);
                    if (!$timeFlag) {
                        self::throwError('500005');
                    }
                    $order->status = AROrder::STATUS_SUCCESS;
                    $order->security_at = Yii::$app->formatter->asTimestamp('now');
                    $order->security_code = self::getOrderSecufity($order);
                    if (!$order->update()) {
                        self::throwError('500006');
                    }

                    $scale = Yii::$app->params['scale'];
                    $amount = $order->amount;
                    $need = ARNeed::findOne(['id' => $order->need_id]);
                    if ($need->type == ARNeed::TYPE_IN) {
                        $need->setScenario(ARNeed::SCENARIO_BUY);
                    } else {
                        $need->setScenario(ARNeed::SCENARIO_SELL);
                    }
                    $need->amount_trading = bcsub(sprintf("%.{$scale}f", $need->amount_trading), $amount, $scale);
                    $need->amount_used = bcadd(sprintf("%.{$scale}f", $need->amount_used), $amount, $scale);
                    if (!$need->update()) {
                        self::getErrorMessge($need);
                    }

                    //创建订单评价
                    OrderEvaluate::create($order);
                    //添加经纪人手续费记录
                    ServiceCharge::AddServiceCharge($order);
                    //更新评分
                    ReplyTime::updateUserScoringTime($order);
                    //更新平台手续费
                    Coin::updatePlatformProfit($order);
                    //更改经纪人交易笔数
                    Broker::changeNum($order->broker, 1);
                    //添加系统信息
                    $user = self::getUser();
                    Chat::addSystemMessage($user, $order->id, 'confirm-receive_finish');
                    $transaction->commit();
                    return true;
                }
            } catch (\Exception $e) {
                $transaction->rollBack();
                throw $e;
            }
        } else {
            self::throwError('500007');
        }
    }

    /**
     * 最近成交列表
     * @author zcy
     */
    public function recentorderlist()
    {

        $model = AROrder::find();
        $model->with(['user', 'oppUser', 'coinType', 'currencyType', 'serviceCharge']);
        $data = $model->where(['status' => AROrder::STATUS_SUCCESS])->limit($this->size)->orderBy(['created_at' => SORT_DESC])->all();
        $rows = ArrayHelper::toArray($data, [
            AROrder::className() => [
                'id',
                'type',
                'buy_id' => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->user->id;
                    } else {
                        return $row->oppUser->id;
                    }

                },
                'buy' => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->user->nickname;
                    } else {
                        return $row->oppUser->nickname;
                    }

                },
                'sell_id' => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->oppUser->id;
                    } else {
                        return $row->user->id;
                    }

                },
                'sell' => function ($row) {
                    if ($row->type == AROrder::TYPE_IN) {
                        return $row->oppUser->nickname;
                    } else {
                        return $row->user->nickname;
                    }

                },
                'coin'       => function ($row) {
                    return $row->coinType->name;
                },
                'currency'   => function ($row) {
                    return $row->currencyType->name;
                },
                'amount',
                'total_price',
                'status',
                'createtime' => function ($row) {
                    return Yii::$app->formatter->asDatetime($row->created_at);
                },
                'security'   => function ($row) {
                    $flag = self::verifyOrderSecufity($row);
                    return ($flag) ? AROrder::SECURITY_SAFE : AROrder::SECURITY_UNSAFE;
                },
            ],
        ]);
        return ['rows' => $rows];
    }

}
